/**
 * Copyright (c) Tapas Mobile.  All Rights Reserved.
 *
 * @author DaiHui 
 * @version 1.0
 */

package com.dotools.preferences;

import java.lang.reflect.Method;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;

import com.dotools.base.CommonConstants;
import com.dotools.debug.LOG;
import com.dotools.reflection.ReflectionUtils;
import com.dotools.thread.ThreadPool;
import com.dotools.utils.Utilities;

// to store big string data such as json from network
// TODO: switch backend to db / file, sharedPref is too too slow
public class BigPreferences {
    private static final boolean LOGV = CommonConstants.IS_DEBUG && false;

    // never change this
    final static String PREFERENCE_NAME = CommonConstants.PROCESS_NAME + "_big";

    static SharedPreferences sSP = null;

    static final Method methodApply;

    static {
        Class<?> clsEditor = ReflectionUtils.loadClassNoThrow(ClassLoader.getSystemClassLoader(),
                "android.content.SharedPreferences$Editor");

        if (clsEditor != null)
            methodApply = ReflectionUtils.findMethodNoThrow(clsEditor, "apply", new Class<?>[] {});
        else
            methodApply = null;
    }

    public static void init() {
        synchronized (BigPreferences.class) {
            sSP = Utilities.getApplicationContext().getSharedPreferences(PREFERENCE_NAME,
                    Context.MODE_PRIVATE);
        }
    }

    public static void finish() {
        sSP = null;
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    private static void asyncCommit(final SharedPreferences.Editor editor) {
        if (editor != null) {
            if (methodApply != null) {
                editor.apply();
            } else {
                ThreadPool.runOnPool(new Runnable() {
                    @Override
                    public void run() {
                        editor.commit();
                    }
                });
            }
        }
    }

    // --------------------------------------------------------------------------------
    // handle string
    // --------------------------------------------------------------------------------
    public static String getString(String key, String defValue) {
        synchronized (BigPreferences.class) {
            return sSP.getString(key, defValue);
        }
    }

    public static void putString(String key, String value) {
        putString(key, value, true);
    }

    public static void putString(String key, String value, boolean bCommitNow) {
        if (LOGV) {
            if (value != null && value.length() > 512) {
                LOG.logE(key + " seems too long. length=" + value.length());
            }
        }

        // TODO: remove this next version
        AppPreferences.remove(key);

        if (hasKey(key)) {
            String old = getString(key, null);
            if (old != null && old.equals(value)) {
                if (LOGV) LOG.logI("value not changed: key=" + key + ", value=" + old);
                return;
            }
        }

        synchronized (BigPreferences.class) {
            SharedPreferences.Editor editor = sSP.edit();
            editor.putString(key, value);

            if (bCommitNow) {
                asyncCommit(editor);
            }
        }
    }

    // --------------------------------------------------------------------------------
    // remove
    // --------------------------------------------------------------------------------
    public static void remove(String key) {
        remove(key, true);
    }

    static void remove(String key, boolean bCommitNow) {
        if (!hasKey(key)) {
            return;
        }

        synchronized (BigPreferences.class) {
            SharedPreferences.Editor editor = sSP.edit();
            editor.remove(key);

            if (bCommitNow) {
                asyncCommit(editor);
            }
        }
    }

    // --------------------------------------------------------------------------------
    // check if key present
    // --------------------------------------------------------------------------------
    static boolean hasKey(String key) {
        synchronized (AppPreferences.class) {
            return sSP.contains(key);
        }
    }
}
